package com.flute.tools.data.file;

import java.io.File;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import com.flute.tools.data.DataIterator;
import com.flute.tools.util.exceptoin.DataParserException;

/**
 * 通用的多文件数据遍历器。
 * 
 * 假设一个文件可以有多个数据，当存在多个这样的文件时，
 * 
 * 可以用此工具类来生成多个文件的统一的数据遍历器。
 * 
 * @author Dave Yang
 * 
 * @param <T>
 */
public class FilesDataIterator<T> implements DataIterator<T> {

	private IFileDataParser<T, File> parser;
	private IFileFilter filter;
	private IFileHandler handler;
	private Iterator<File> fileIt;
	private File[] files;
	private DataIterator<T> currentIt;

	public FilesDataIterator(String folder) {
		File file = new File(folder);
		this.files = file.listFiles();
	}

	public FilesDataIterator(File[] files) {
		this.files = files;
	}

	private void initialFileIterator() {
		List<File> list = new ArrayList<File>();
		if (files != null) {
			for (File f : files) {
				if (filter == null || filter.isValidFile(f)) {
					list.add(f);
				}
			}
		}

		fileIt = list.iterator();
	}

	public IFileFilter getFilter() {
		return filter;
	}

	public void setFilter(IFileFilter filter) {
		this.filter = filter;
	}

	public IFileDataParser<T, File> getParser() {
		return parser;
	}

	public void setParser(IFileDataParser<T, File> parser) {
		this.parser = parser;
	}

	@Override
	public void close() {
		if (currentIt != null) {
			currentIt.close();
		}
	}

	@Override
	public boolean hasNext() {
		if (currentIt == null || !currentIt.hasNext()) {
			boolean success = false;
			while (!success && getFileIterator().hasNext()) {
				if (currentIt != null) {
					currentIt.close();
				}
				File file = getFileIterator().next();
				try {
					currentIt = parser.parse(file);
					if (handler != null) {
						handler.successFile(file);
					}
					success = true;
				} catch (DataParserException e) {
					handler.failFile(file, e);
				}
			}
		}

		if (currentIt != null) {
			if (currentIt.hasNext()) {
				return true;
			} else {
				currentIt.close();
				return false;
			}
		} else {
			return false;
		}
	}

	private Iterator<File> getFileIterator() {
		if (fileIt == null) {
			initialFileIterator();
		}

		return fileIt;
	}

	@Override
	public T next() {
		return currentIt.next();
	}

	@Override
	public void reset() {
		initialFileIterator();
		if (currentIt != null) {
			currentIt.close();
		}
		currentIt = null;
	}

	public IFileHandler getHandler() {
		return handler;
	}

	public void setHandler(IFileHandler handler) {
		this.handler = handler;
	}

}
